package org.artifact.core.plugin.agent;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.watch.SimpleWatcher;
import cn.hutool.core.io.watch.WatchMonitor;
import cn.hutool.core.io.watch.WatchUtil;
import cn.hutool.core.io.watch.watchers.DelayWatcher;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.system.SystemUtil;
import com.sun.tools.attach.*;
import org.artifact.core.lang.AbstractPlugin;
import org.artifact.core.server.ServerConfig;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.util.List;
import java.util.Map;

public class AgentPlugin extends AbstractPlugin {

    private static final Log log = LogFactory.get(AgentPlugin.class);

    String patch = "patch.yml";

    String jar = "JavaAgent.jar";

    private WatchMonitor watchMonitor;

    volatile boolean isStart = false;

    class FileWatcher extends SimpleWatcher {

        @Override
        public void onModify(WatchEvent<?> event, Path currentPath) {
            try {
                if (isStart && FileUtil.exist(jar)){
                    loadAgent();
                }else {
                    log.warn("not fond JavaAgent.jar");
                }
            } catch (Exception e) {
                log.error(e);
            }

        }
    }

    @Override
    public boolean start() {
        this.patch = ServerConfig.me().deepGet("plugins.agent.patch");

        this.jar = ServerConfig.me().deepGet("plugins.agent.jar");

        // 1.监听文件变更
        File file = FileUtil.file(patch);

        watchMonitor = WatchUtil.createModify(file, new DelayWatcher(new FileWatcher(), 500));
        watchMonitor.start();
        isStart = true;
        return true;
    }

    private void loadAgent() throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException {
        String content = FileUtil.readString(patch, CharsetUtil.CHARSET_UTF_8);
        Yaml yaml = new Yaml();
        Map map = yaml.loadAs(content, Map.class);
        JSONObject json = JSONUtil.parseObj(map);
        List<VirtualMachineDescriptor> list = VirtualMachine.list();
        for (VirtualMachineDescriptor virtualMachineDescriptor : list) {
            if (virtualMachineDescriptor.id().equals(SystemUtil.getCurrentPID() + "")) {
                VirtualMachine vm = VirtualMachine.attach(SystemUtil.getCurrentPID() + "");
                vm.loadAgent(FileUtil.file(this.jar).getPath(), json.toString());
                vm.detach();
            }
        }
    }

    @Override
    public boolean stop() {
        isStart = false;
        return true;
    }
}
